home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2001 September / PC-WELT 9-2001.ISO / software / hw / brennen / flask_src.exe / Resizer / resizer.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-06  |  50.2 KB  |  2,316 lines

  1. /* 
  2.  *  resizer.cpp   - Original code from Avery Lee's Virtual Dub
  3.  *
  4.  *    Copyright (C) Alberto Vigata - ultraflask@yahoo.com - January 2000
  5.  *
  6.  *  This file is part of FlasKMPEG, a free MPEG to MPEG/AVI converter
  7.  *    
  8.  *  FlasKMPEG is free software; you can redistribute it and/or modify
  9.  *  it under the terms of the GNU General Public License as published by
  10.  *  the Free Software Foundation; either version 2, or (at your option)
  11.  *  any later version.
  12.  *   
  13.  *  FlasKMPEG is distributed in the hope that it will be useful,
  14.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  *  GNU General Public License for more details.
  17.  *   
  18.  *  You should have received a copy of the GNU General Public License
  19.  *  along with GNU Make; see the file COPYING.  If not, write to
  20.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  21.  *
  22.  */
  23.  
  24.  
  25.  
  26. #include <windows.h>
  27. #include <commctrl.h>
  28. #include <crtdbg.h>
  29. #include <assert.h>
  30. #include <stdio.h>
  31. #include <math.h>
  32.  
  33.  
  34. #include "misc.h"
  35. #include "..\mmx.h"
  36.  
  37.  
  38. #include "filter.h"
  39. #include "resample.h"
  40. #include "resizer.h"
  41.  
  42. extern HINSTANCE g_hInst;
  43.  
  44. struct MyFilterData {
  45.     long new_x, new_y, new_xf, new_yf;
  46.     int filter_mode;
  47.     COLORREF    rgbColor;
  48.  
  49.     HBRUSH        hbrColor;
  50.     IFilterPreview *ifp;
  51.     Pixel *cubic_rows;
  52.     int *x_table;
  53.     int *y_table;
  54.     Pixel **row_table;
  55.     int x_filtwidth;
  56.     int y_filtwidth;
  57.     int *cubic4_tbl;
  58.  
  59.     bool    fLetterbox;
  60. };
  61.  
  62. MyFilterData        mfd;
  63. ///////////////////////
  64.  
  65. #if 0
  66.  
  67. __int64 last_upd;
  68. __int64 profile_column=0;
  69. __int64 profile_row=0;
  70. int profile_column_count=0;
  71. int profile_row_count=0;
  72.  
  73. #define PROFILE_START                                \
  74.         __int64 start_clock;                        \
  75.         __asm rdtsc                                    \
  76.         __asm mov dword ptr start_clock+0,eax        \
  77.         __asm mov dword ptr start_clock+4,edx
  78.  
  79. #define PROFILE_ADD(x)                                \
  80.         __int64 stop_clock;                            \
  81.         {__asm rdtsc                                    \
  82.         __asm mov dword ptr stop_clock+0,eax        \
  83.         __asm mov dword ptr stop_clock+4,edx}        \
  84.         profile_##x += stop_clock - start_clock;    \
  85.         profile_##x##_count ++;
  86.  
  87. static inline void stats_print() {
  88.     __int64 clk;
  89.  
  90.     __asm rdtsc
  91.     __asm mov dword ptr clk,eax
  92.     __asm mov dword ptr clk+4,edx
  93.  
  94.     if (clk - last_upd > 450000000) {
  95.         char buf[128];
  96.         last_upd = clk;
  97.  
  98.         if (profile_row_count && profile_column_count) {
  99.             sprintf(buf, "%I64d (%d), %I64d (%d) per scanline\n", profile_row/profile_row_count, profile_row_count, profile_column/profile_column_count, profile_column_count);
  100.             OutputDebugString(buf);
  101.         }
  102.     }
  103. }
  104. #else
  105. static inline void stats_print() {}
  106. #define PROFILE_START
  107. #define PROFILE_ADD(x)
  108. #endif
  109.  
  110. ///////////////////////
  111.  
  112. #define USE_ASM
  113.  
  114. extern "C" void asm_resize_interp_run(
  115.             void *dst,
  116.             void *src,
  117.             unsigned long width,
  118.             unsigned long height,
  119.             unsigned long srcstride,
  120.             unsigned long dststride,
  121.             unsigned long xaccum,
  122.             unsigned long yaccum,
  123.             unsigned long x_inc,
  124.             unsigned long y_inc);
  125.  
  126. extern "C" void asm_resize_interp_row_run(
  127.             void *dst,
  128.             void *src,
  129.             unsigned long width,
  130.             unsigned long xaccum,
  131.             unsigned long x_inc);
  132.  
  133. extern "C" void asm_resize_interp_col_run(
  134.             void *dst,
  135.             void *src1,
  136.             void *src2,
  137.             unsigned long width,
  138.             unsigned long yaccum);
  139.  
  140. #if 0
  141. extern "C" asm_resize_interp_table_run(
  142.             void *dst,
  143.             void *src,
  144.             unsigned long width,
  145.             unsigned long height,
  146.             unsigned long srcstride,
  147.             unsigned long dststride,
  148.             unsigned long xaccum,
  149.             unsigned long yaccum,
  150.             unsigned long x_inc,
  151.             unsigned long y_inc,
  152.             unsigned char *table);
  153. #endif
  154.  
  155. extern "C" void asm_resize_ccint(Pixel *dst, Pixel *src1, Pixel *src2, Pixel *src3, Pixel *src4, long count, long xaccum, long xint, int *table);
  156. extern "C" void asm_resize_ccint_col(Pixel *dst, Pixel *src1, Pixel *src2, Pixel *src3, Pixel *src4, long count, const int *table);
  157.  
  158. static void cc_row(Pixel *dst, Pixel *src, long w, long xs_left, long xs_right, long xaccum, long xinc, int *table);
  159. static long accum_start(long inc);
  160.  
  161. ///////////////////////
  162.  
  163.  
  164.  
  165. #define ACCEL_BICUBICBY2        (1)
  166. #define ACCEL_BILINEARBY2        (2)
  167.  
  168. static char *filter_names[]={
  169.     "Nearest neighbor",
  170.     "Bilinear",
  171.     "Bicubic",
  172.     "Precise bilinear",
  173.     "Precise bicubic",
  174. };
  175.  
  176.  
  177. ////////////////////
  178.  
  179. int revcolor(int c) {
  180.     return ((c>>16)&0xff) | (c&0xff00) | ((c&0xff)<<16);
  181. }
  182.  
  183. ////////////////////
  184.  
  185. static const __int64 MMX_roundval = 0x0000200000002000i64;
  186.  
  187. static long __declspec(naked) resize_table_row_MMX(Pixel *out, Pixel *in, int *filter, int filter_width, PixDim w, long accum, long frac) {
  188.  
  189.     __asm {
  190.         push        ebp
  191.         push        esi
  192.         push        edi
  193.         push        edx
  194.         push        ecx
  195.         push        ebx
  196.  
  197.         mov            eax,[esp + 24 + 24]
  198.         mov            ebp,[esp + 20 + 24]
  199.         mov            ebx,[esp + 8 + 24]
  200.         mov            edi,[esp + 4 + 24]
  201.  
  202.         mov            esi,eax
  203.         mov            edx,eax
  204.  
  205.         mov            ecx,[esp + 16 + 24]
  206.         shr            ecx,1
  207.         mov            [esp+16+24],ecx
  208.         test        ecx,1
  209.         jnz            pixelloop_odd_pairs
  210.  
  211. pixelloop_even_pairs:
  212.         shr            esi,14
  213.         and            edx,0000ff00h
  214.         and            esi,0fffffffch
  215.  
  216.         mov            ecx,[esp + 16 + 24]
  217.         shr            edx,5
  218.         add            esi,ebx
  219.         imul        edx,ecx
  220.         add            eax,[esp + 28 + 24]
  221.         add            edx,[esp + 12 + 24]
  222.  
  223.         movq        mm6,MMX_roundval
  224.         pxor        mm3,mm3
  225.         shr            ecx,1
  226.         movq        mm7,mm6
  227.         pxor        mm5,mm5
  228.  
  229. coeffloop_unaligned_even_pairs:
  230.         movd        mm0,[esi]        ;mm0 = [x1][r1][g1][b1]
  231.         paddd        mm7,mm5
  232.  
  233.         paddd        mm6,mm3
  234.         pxor        mm5,mm5
  235.  
  236.         movd        mm2,[esi+4]        ;mm2 = [x0][r0][g0][b0]
  237.         punpcklbw    mm0,mm5            ;mm0 = [x1][r1][g1][b1]
  238.  
  239.         punpcklbw    mm2,mm5            ;mm2 = [x0][r0][g0][b0]
  240.         movq        mm1,mm0
  241.  
  242.         movq        mm4,[edx]        ;mm4 = [filter0][filter1]
  243.         punpcklwd    mm0,mm2            ;mm0 = [g0][g1][b0][b1]
  244.  
  245.         movd        mm3,[esi+8]        ;mm3 = [x3][r3][g3][b3]
  246.         punpckhwd    mm1,mm2            ;mm1 = [x0][x1][r0][r1]
  247.  
  248.         movd        mm2,[esi+12]    ;mm2 = [x2][r2][g2][b2]
  249. ;        packssdw    mm4,mm4            ;mm4 = [filt0][filt1][filt0][filt1]
  250.  
  251.         pmaddwd        mm0,mm4
  252.         punpcklbw    mm2,mm5            ;mm2 = [x2][r2][g2][b2]
  253.  
  254.         pmaddwd        mm1,mm4
  255.         punpcklbw    mm3,mm5            ;mm3 = [x3][r3][g3][b3]
  256.  
  257.         movq        mm5,mm3
  258.         punpcklwd    mm3,mm2            ;mm3 = [g2][g3][b2][b3]
  259.  
  260.         movq        mm4,[edx+8]        ;mm4 = [filter2][filter3]
  261.         paddd        mm6,mm0
  262.  
  263.         paddd        mm7,mm1
  264. ;        packssdw    mm4,mm4            ;mm4 = [filt2][filt3][filt2][filt3]
  265.  
  266.         punpckhwd    mm5,mm2            ;mm1 = [x2][x3][r2][r3]
  267.         pmaddwd        mm3,mm4
  268.  
  269.         pmaddwd        mm5,mm4
  270.         add            edx,16
  271.  
  272.         add            esi,16
  273.         dec            ecx
  274.  
  275.         jne            coeffloop_unaligned_even_pairs
  276.  
  277.         paddd        mm6,mm3
  278.         paddd        mm7,mm5
  279.  
  280.         psrad        mm6,14
  281.         psrad        mm7,14
  282.  
  283.         packssdw    mm6,mm7
  284.         add            edi,4
  285.  
  286.         packuswb    mm6,mm6
  287.         dec            ebp
  288.  
  289.         mov            esi,eax
  290.         mov            edx,eax
  291.  
  292.         movd        [edi-4],mm6
  293.         jne            pixelloop_even_pairs
  294.  
  295.         pop            ebx
  296.         pop            ecx
  297.         pop            edx
  298.         pop            edi
  299.         pop            esi
  300.         pop            ebp
  301.  
  302.         ret
  303.  
  304. ;----------------------------------------------------------------
  305.  
  306. pixelloop_odd_pairs:
  307.         shr            esi,14
  308.         and            edx,0000ff00h
  309.         and            esi,0fffffffch
  310.  
  311.         mov            ecx,[esp + 16 + 24]
  312.         shr            edx,5
  313.         add            esi,ebx
  314.         imul        edx,ecx
  315.         add            eax,[esp + 28 + 24]
  316.         add            edx,[esp + 12 + 24]
  317.  
  318.         movq        mm6,MMX_roundval
  319.         pxor        mm3,mm3
  320.         shr            ecx,1
  321.         movq        mm7,mm6
  322.         pxor        mm5,mm5
  323.  
  324. coeffloop_unaligned_odd_pairs:
  325.         movd        mm0,[esi]        ;mm0 = [x1][r1][g1][b1]
  326.         paddd        mm7,mm5
  327.  
  328.         paddd        mm6,mm3
  329.         pxor        mm5,mm5
  330.  
  331.         movd        mm2,[esi+4]        ;mm2 = [x0][r0][g0][b0]
  332.         punpcklbw    mm0,mm5            ;mm0 = [x1][r1][g1][b1]
  333.  
  334.         punpcklbw    mm2,mm5            ;mm2 = [x0][r0][g0][b0]
  335.         movq        mm1,mm0
  336.  
  337.         movq        mm4,[edx]        ;mm4 = [filter0][filter1]
  338.         punpcklwd    mm0,mm2            ;mm0 = [g0][g1][b0][b1]
  339.  
  340.         movd        mm3,[esi+8]        ;mm3 = [x3][r3][g3][b3]
  341.         punpckhwd    mm1,mm2            ;mm1 = [x0][x1][r0][r1]
  342.  
  343.         movd        mm2,[esi+12]    ;mm2 = [x2][r2][g2][b2]
  344. ;        packssdw    mm4,mm4            ;mm4 = [filt0][filt1][filt0][filt1]
  345.  
  346.         pmaddwd        mm0,mm4
  347.         punpcklbw    mm2,mm5            ;mm2 = [x2][r2][g2][b2]
  348.  
  349.         pmaddwd        mm1,mm4
  350.         punpcklbw    mm3,mm5            ;mm3 = [x3][r3][g3][b3]
  351.  
  352.         movq        mm5,mm3
  353.         punpcklwd    mm3,mm2            ;mm3 = [g2][g3][b2][b3]
  354.  
  355.         movq        mm4,[edx+8]        ;mm4 = [filter2][filter3]
  356.         paddd        mm6,mm0
  357.  
  358.         paddd        mm7,mm1
  359. ;        packssdw    mm4,mm4            ;mm4 = [filt2][filt3][filt2][filt3]
  360.  
  361.         punpckhwd    mm5,mm2            ;mm1 = [x2][x3][r2][r3]
  362.         pmaddwd        mm3,mm4
  363.  
  364.         pmaddwd        mm5,mm4
  365.         add            edx,16
  366.  
  367.         add            esi,16
  368.         dec            ecx
  369.  
  370.         jne            coeffloop_unaligned_odd_pairs
  371.  
  372.         paddd        mm6,mm3
  373.         paddd        mm7,mm5
  374.  
  375.         ;finish up odd pair
  376.  
  377.         movd        mm2,[esi+4]        ;mm2 = [x0][r0][g0][b0]
  378.         pxor        mm5,mm5
  379.         movd        mm0,[esi]        ;mm0 = [x1][r1][g1][b1]
  380.         punpcklbw    mm2,mm5            ;mm2 = [x0][r0][g0][b0]
  381.         punpcklbw    mm0,mm5            ;mm0 = [x1][r1][g1][b1]
  382.         movq        mm1,mm0
  383.         punpcklwd    mm0,mm2            ;mm0 = [g0][g1][b0][b1]
  384.         punpckhwd    mm1,mm2            ;mm1 = [x0][x1][r0][r1]
  385.  
  386.         movq        mm4,[edx]        ;mm4 = [filter0][filter1]
  387. ;        packssdw    mm4,mm4            ;mm4 = [filt0][filt1][filt0][filt1]
  388.  
  389.         pmaddwd        mm0,mm4
  390.         pmaddwd        mm1,mm4
  391.  
  392.         paddd        mm6,mm0
  393.         paddd        mm7,mm1
  394.  
  395.         ;combine into pixel
  396.  
  397.         psrad        mm6,14
  398.  
  399.         psrad        mm7,14
  400.  
  401.         packssdw    mm6,mm7
  402.         add            edi,4
  403.  
  404.         packuswb    mm6,mm6
  405.         dec            ebp
  406.  
  407.         mov            esi,eax
  408.         mov            edx,eax
  409.  
  410.         movd        [edi-4],mm6
  411.         jne            pixelloop_odd_pairs
  412.  
  413.         pop            ebx
  414.         pop            ecx
  415.         pop            edx
  416.         pop            edi
  417.         pop            esi
  418.         pop            ebp
  419.  
  420.         ret
  421.  
  422.  
  423.     }
  424. }
  425.  
  426. static long __declspec(naked) resize_table_row_by2linear_MMX(Pixel *out, Pixel *in, PixDim w) {
  427.     static const __int64 x0002000200020002 = 0x0002000200020002i64;
  428.  
  429.     __asm {
  430.         push        ebp
  431.         push        esi
  432.         push        edi
  433.         push        ebx
  434.  
  435.         mov            ebp,[esp + 12 + 16]        ;ebp = pixel counter
  436.         mov            eax,[esp + 16 + 16]        ;eax = accumulator
  437.         shl            ebp,2
  438.         neg            ebp
  439.         mov            edi,[esp +  4 + 16]        ;edi = destination pointer
  440.         mov            esi,[esp + 8 + 16]        ;esi = source
  441.         movq        mm6,x0002000200020002
  442.         pxor        mm7,mm7
  443.  
  444.         ;load row pointers!
  445.  
  446.         and            ebp,0fffffff8h
  447.         jz            oddpixeltest
  448.  
  449.         sub            esi,ebp
  450.         sub            edi,ebp
  451.         sub            esi,ebp
  452.  
  453.         test        dword ptr [esp+8+16],4
  454.         jnz            pixelloop_unaligned
  455.  
  456. pixelloop:
  457.         movd        mm0,[esi+ebp*2+4]
  458.  
  459.         movq        mm1,[esi+ebp*2+8]
  460.         punpcklbw    mm0,mm7
  461.  
  462.         movq        mm2,mm1
  463.         punpcklbw    mm1,mm7
  464.  
  465.         movq        mm3,[esi+ebp*2+16]
  466.         punpckhbw    mm2,mm7
  467.  
  468.         movq        mm4,mm3
  469.         punpcklbw    mm3,mm7
  470.  
  471.         punpckhbw    mm4,mm7
  472.         paddw        mm1,mm1
  473.  
  474.         paddw        mm3,mm3
  475.         paddw        mm0,mm2
  476.  
  477.         paddw        mm2,mm4
  478.         paddw        mm0,mm1
  479.  
  480.         paddw        mm2,mm3
  481.         paddw        mm0,mm6
  482.  
  483.         paddw        mm2,mm6
  484.         psraw        mm0,2
  485.  
  486.         psraw        mm2,2
  487.         packuswb    mm0,mm0
  488.  
  489.         packuswb    mm2,mm2
  490.         add            ebp,8
  491.  
  492.         movd        [edi+ebp-8],mm0
  493.  
  494.         movd        [edi+ebp-4],mm2
  495.         jne            pixelloop
  496.         jmp            short oddpixeltest
  497.  
  498. pixelloop_unaligned:
  499.         movq        mm0,[esi+ebp*2+4]
  500.  
  501.         movq        mm1,mm0
  502.         punpcklbw    mm0,mm7
  503.  
  504.         movq        mm2,[esi+ebp*2+12]
  505.         punpckhbw    mm1,mm7
  506.  
  507.         movq        mm3,mm2
  508.         punpcklbw    mm2,mm7
  509.  
  510.         movd        mm4,[esi+ebp*2+20]
  511.         punpckhbw    mm3,mm7
  512.  
  513.         punpcklbw    mm4,mm7
  514.         paddw        mm1,mm1
  515.  
  516.         paddw        mm3,mm3
  517.         paddw        mm0,mm2
  518.  
  519.         paddw        mm2,mm4
  520.         paddw        mm0,mm1
  521.  
  522.         paddw        mm2,mm3
  523.         paddw        mm0,mm6
  524.  
  525.         paddw        mm2,mm6
  526.         psraw        mm0,2
  527.  
  528.         psraw        mm2,2
  529.         packuswb    mm0,mm0
  530.  
  531.         packuswb    mm2,mm2
  532.         add            ebp,8
  533.  
  534.         movd        [edi+ebp-8],mm0
  535.  
  536.         movd        [edi+ebp-4],mm2
  537.         jne            pixelloop_unaligned
  538.  
  539.         ;odd pixel?
  540.  
  541. oddpixeltest:
  542.         test        dword ptr [esp+12+16],1
  543.         jz            xit
  544.  
  545.             movd        mm0,[esi+4]
  546.  
  547.             movd        mm1,[esi+8]
  548.             punpcklbw    mm0,mm7
  549.             movd        mm2,[esi+12]
  550.             punpcklbw    mm1,mm7
  551.  
  552.             punpcklbw    mm2,mm7
  553.             paddw        mm1,mm1
  554.  
  555.             paddw        mm0,mm2
  556.             paddw        mm1,mm6
  557.  
  558.             paddw        mm1,mm0
  559.  
  560.             psraw        mm1,2
  561.  
  562.             packuswb    mm1,mm1
  563.  
  564.             movd        [edi],mm1
  565.  
  566. xit:
  567.         pop            ebx
  568.         pop            edi
  569.         pop            esi
  570.         pop            ebp
  571.  
  572.         ret
  573.     }
  574. }
  575.  
  576. static long __declspec(naked) resize_table_row_by2cubic_MMX(Pixel *out, Pixel *in, PixDim w, unsigned long accum, unsigned long fstep, unsigned long istep) {
  577.     static const __int64 x0004000400040004 = 0x0004000400040004i64;
  578.     __asm {
  579.         push        ebp
  580.         push        esi
  581.         push        edi
  582.         push        edx
  583.         push        ecx
  584.         push        ebx
  585.  
  586.         mov            ebp,[esp + 12 + 24]        ;ebp = pixel counter
  587.         mov            eax,[esp + 16 + 24]        ;eax = accumulator
  588.         shl            ebp,2
  589.         mov            ebx,[esp + 20 + 24]        ;ebx = fractional step
  590.         neg            ebp
  591.         mov            edi,[esp + 4 + 24]        ;edi = destination pointer
  592.         mov            ecx,[esp + 24 + 24]        ;ecx = integer step
  593.  
  594.         ;load row pointers!
  595.  
  596.         mov            esi,[esp + 8 + 24]        ;esi = row pointer table
  597.  
  598.         sub            esi,ebp
  599.         sub            esi,ebp
  600.  
  601.         sub            edi,ebp
  602.         movq        mm6,x0004000400040004
  603.         pxor        mm7,mm7
  604.  
  605. pixelloop:
  606.         movd        mm0,[esi+ebp*2+4]
  607.  
  608.         movd        mm1,[esi+ebp*2+12]
  609.         punpcklbw    mm0,mm7
  610.         movd        mm2,[esi+ebp*2+16]
  611.         punpcklbw    mm1,mm7
  612.         movd        mm3,[esi+ebp*2+20]
  613.         punpcklbw    mm2,mm7
  614.         movd        mm4,[esi+ebp*2+28]
  615.         punpcklbw    mm3,mm7
  616.  
  617.         punpcklbw    mm4,mm7
  618.         psllw        mm2,3
  619.  
  620.         paddw        mm1,mm3
  621.         paddw        mm0,mm4
  622.  
  623.         movq        mm3,mm1
  624.         paddw        mm2,mm6
  625.  
  626.         psllw        mm1,2
  627.         psubw        mm2,mm0
  628.  
  629.         paddw        mm1,mm3
  630.         add            ebp,4
  631.  
  632.         paddw        mm2,mm1
  633.  
  634.         psraw        mm2,4
  635.  
  636.         packuswb    mm2,mm2
  637.  
  638.         movd        [edi+ebp-4],mm2
  639.         jne            pixelloop
  640.  
  641.         pop            ebx
  642.         pop            ecx
  643.         pop            edx
  644.         pop            edi
  645.         pop            esi
  646.         pop            ebp
  647.  
  648.         ret
  649.     }
  650. }
  651.  
  652. static void resize_table_row(Pixel *out, Pixel *in, int *filter, int filter_width, PixDim w, PixDim w_left, PixDim w_right, PixDim w2, long accum, long frac, int accel_code) {
  653.     Pixel *in_bottom, *in_top;
  654.  
  655.     in_bottom = in;
  656.     in_top = in + w2;
  657.     in -= filter_width/2 - 1;
  658.  
  659.     if (w_left) do {
  660.         int x, r, g, b;
  661.         Pixel *in2;
  662.         int *filter2;
  663.  
  664.         x = filter_width;
  665.         in2 = in + (accum>>16);
  666.         filter2 = filter + ((accum>>8) & 255)*filter_width;
  667.         r = g = b = 0;
  668.  
  669.         if (MMX_enabled)
  670.             do {
  671.                 Pixel c2, c1;
  672.                 int a1, a2;
  673.  
  674.                 if (in2 < in_bottom)
  675.                     c1 = *in_bottom;
  676.                 else
  677.                     c1 =  *in2;
  678.                 ++in2;
  679.                 if (in2 < in_bottom)
  680.                     c2 = *in_bottom;
  681.                 else
  682.                     c2 =  *in2;
  683.                 ++in2;
  684.  
  685.                 a1 = *filter2; filter2+=2;
  686.                 a2 = a1>>16;
  687.                 a1 = (signed short) a1;
  688.  
  689.                 r += ((c1>>16)&255) * a1;
  690.                 g += ((c1>> 8)&255) * a1;
  691.                 b += ((c1    )&255) * a1;
  692.                 r += ((c2>>16)&255) * a2;
  693.                 g += ((c2>> 8)&255) * a2;
  694.                 b += ((c2    )&255) * a2;
  695.  
  696.             } while(x-=2);
  697.         else
  698.             do {
  699.                 Pixel c;
  700.                 int a;
  701.  
  702.                 if (in2 < in_bottom)
  703.                     c = *in_bottom;
  704.                 else
  705.                     c =  *in2;
  706.                 ++in2;
  707.  
  708.                 a = *filter2++;
  709.  
  710.                 r += ((c>>16)&255) * a;
  711.                 g += ((c>> 8)&255) * a;
  712.                 b += ((c    )&255) * a;
  713.  
  714.             } while(--x);
  715.  
  716.         r = (r + 8192)>>14;
  717.         g = (g + 8192)>>14;
  718.         b = (b + 8192)>>14;
  719.  
  720.         if (r<0) r=0; else if (r>255) r=255;
  721.         if (g<0) g=0; else if (g>255) g=255;
  722.         if (b<0) b=0; else if (b>255) b=255;
  723.  
  724.         *out++ = (r<<16) + (g<<8) + b;
  725.  
  726.         accum += frac;
  727.  
  728.     } while(--w_left);
  729.  
  730.     if (w)
  731.         if (MMX_enabled) {
  732.             PROFILE_START
  733.  
  734.             if (accel_code == ACCEL_BICUBICBY2) {
  735.                 resize_table_row_by2cubic_MMX(out, in + (accum>>16), w, accum<<16, frac<<16, frac>>16);
  736.  
  737.                 accum += frac*w;
  738.             } else if (accel_code == ACCEL_BILINEARBY2) {
  739.                 resize_table_row_by2linear_MMX(out, in + (accum>>16), w);
  740.  
  741.                 accum += frac*w;
  742.             } else
  743.                 accum = resize_table_row_MMX(out, in, filter, filter_width, w, accum, frac);
  744.  
  745.             PROFILE_ADD(row)
  746.  
  747.             out += w;
  748.         } else
  749.             do {
  750.                 int x, r, g, b;
  751.                 Pixel *in2;
  752.                 int *filter2;
  753.  
  754.                 x = filter_width;
  755.                 in2 = in + (accum>>16);
  756.                 filter2 = filter + ((accum>>8) & 255)*filter_width;
  757.                 r = g = b = 0;
  758.                 do {
  759.                     Pixel c;
  760.                     int a;
  761.  
  762.                     c =  *in2++;
  763.                     a = *filter2++;
  764.  
  765.                     r += ((c>>16)&255) * a;
  766.                     g += ((c>> 8)&255) * a;
  767.                     b += ((c    )&255) * a;
  768.  
  769.                 } while(--x);
  770.  
  771.                 r = (r + 8192)>>14;
  772.                 g = (g + 8192)>>14;
  773.                 b = (b + 8192)>>14;
  774.  
  775.                 if (r<0) r=0; else if (r>255) r=255;
  776.                 if (g<0) g=0; else if (g>255) g=255;
  777.                 if (b<0) b=0; else if (b>255) b=255;
  778.  
  779.                 *out++ = (r<<16) + (g<<8) + b;
  780.  
  781.                 accum += frac;
  782.             } while(--w);
  783.  
  784.     if (w_right) do {
  785.         int x, r, g, b;
  786.         Pixel *in2;
  787.         int *filter2;
  788.  
  789.         x = filter_width;
  790.         in2 = in + (accum>>16);
  791.         filter2 = filter + ((accum>>8) & 255)*filter_width;
  792.         r = g = b = 0;
  793.  
  794.         if (MMX_enabled)
  795.             do {
  796.                 Pixel c1, c2;
  797.                 int a1, a2;
  798.  
  799.                 if (in2 >= in_top)
  800.                     c1 = in_top[-1];
  801.                 else
  802.                     c1 =  *in2++;
  803.                 if (in2 >= in_top)
  804.                     c2 = in_top[-1];
  805.                 else
  806.                     c2 =  *in2++;
  807.  
  808.                 a1 = *filter2; filter2+=2;
  809.                 a2 = a1>>16;
  810.                 a1 = (signed short) a1;
  811.  
  812.                 r += ((c1>>16)&255) * a1;
  813.                 g += ((c1>> 8)&255) * a1;
  814.                 b += ((c1    )&255) * a1;
  815.                 r += ((c2>>16)&255) * a2;
  816.                 g += ((c2>> 8)&255) * a2;
  817.                 b += ((c2    )&255) * a2;
  818.  
  819.             } while(x-=2);
  820.         else
  821.             do {
  822.                 Pixel c;
  823.                 int a;
  824.  
  825.                 if (in2 >= in_top)
  826.                     c = in_top[-1];
  827.                 else
  828.                     c =  *in2++;
  829.  
  830.                 a = *filter2++;
  831.  
  832.                 r += ((c>>16)&255) * a;
  833.                 g += ((c>> 8)&255) * a;
  834.                 b += ((c    )&255) * a;
  835.  
  836.             } while(--x);
  837.  
  838.         r = (r + 8192)>>14;
  839.         g = (g + 8192)>>14;
  840.         b = (b + 8192)>>14;
  841.  
  842.         if (r<0) r=0; else if (r>255) r=255;
  843.         if (g<0) g=0; else if (g>255) g=255;
  844.         if (b<0) b=0; else if (b>255) b=255;
  845.  
  846.         *out++ = (r<<16) + (g<<8) + b;
  847.  
  848.         accum += frac;
  849.  
  850.     } while(--w_right);
  851. }
  852.  
  853. static long __declspec(naked) resize_table_col_MMX(Pixel *out, Pixel **in_table, int *filter, int filter_width, PixDim w, long frac) {
  854.     __asm {
  855.         push        ebp
  856.         push        esi
  857.         push        edi
  858.         push        edx
  859.         push        ecx
  860.         push        ebx
  861.  
  862.         mov            ebp,[esp + 20 + 24]        ;ebp = pixel counter
  863.         mov            edi,[esp + 4 + 24]        ;edi = destination pointer
  864.  
  865.         mov            edx,[esp + 12 + 24]
  866.         mov            eax,[esp + 24 + 24]
  867.         shl            eax,2
  868.         imul        eax,[esp + 16 + 24]
  869.         add            edx,eax
  870.         mov            [esp + 12 + 24], edx    ;[esp+12+28] = filter pointer
  871.  
  872.         mov            ecx,[esp + 16 + 24]
  873.         shr            ecx,1
  874.         mov            [esp + 16 + 24],ecx        ;ecx = filter pair count
  875.  
  876.         xor            ebx,ebx                    ;ebx = source offset 
  877.  
  878.         mov            ecx,[esp + 16 + 24]        ;ecx = filter width counter
  879.         mov            edx,[esp + 12 + 24]        ;edx = filter bank pointer
  880. pixelloop:
  881.         mov            eax,[esp + 8 + 24]        ;esi = row pointer table
  882.         movq        mm6,MMX_roundval
  883.         pxor        mm5,mm5
  884.         movq        mm7,mm6
  885.         pxor        mm0,mm0
  886.         pxor        mm1,mm1
  887. coeffloop:
  888.         mov            esi,[eax]
  889.         paddd        mm6,mm0
  890.  
  891.         movd        mm0,[esi+ebx]    ;mm0 = [0][0][0][0][x0][r0][g0][b0]
  892.         paddd        mm7,mm1
  893.  
  894.         movq        mm4,[edx]        ;mm4 = [filter1][filter0][filter1][filter0]
  895.  
  896.         mov            esi,[eax+4]
  897.         add            eax,8
  898.  
  899.         movd        mm2,[esi+ebx]    ;mm2 = [0][0][0][0][x1][r1][g1][b1]
  900.         punpcklbw    mm0,mm5            ;mm0 = [x0][r0][g0][b0]
  901.  
  902.         punpcklbw    mm2,mm5            ;mm2 = [x1][r1][g1][b1]
  903.  
  904.         movq        mm1,mm0            ;mm1 = [x0][r0][g0][b0]
  905.         punpcklwd    mm0,mm2            ;mm0 = [g1][g0][b1][b0]
  906.  
  907.         pmaddwd        mm0,mm4
  908.         punpckhwd    mm1,mm2            ;mm1 = [x1][x0][r1][r0]
  909.  
  910.         pmaddwd        mm1,mm4
  911.         add            edx,8
  912.  
  913.         dec            ecx
  914.         jne            coeffloop
  915.  
  916.         paddd        mm6,mm0
  917.         paddd        mm7,mm1
  918.  
  919.         psrad        mm6,14
  920.         psrad        mm7,14
  921.         add            edi,4
  922.         packssdw    mm6,mm7
  923.         add            ebx,4
  924.         packuswb    mm6,mm6
  925.         dec            ebp
  926.  
  927.         mov            ecx,[esp + 16 + 24]        ;ecx = filter width counter
  928.         mov            edx,[esp + 12 + 24]        ;edx = filter bank pointer
  929.  
  930.         movd        [edi-4],mm6
  931.         jne            pixelloop
  932.  
  933.         pop            ebx
  934.         pop            ecx
  935.         pop            edx
  936.         pop            edi
  937.         pop            esi
  938.         pop            ebp
  939.  
  940.         ret
  941.     }
  942. }
  943.  
  944. static long __declspec(naked) resize_table_col_by2linear_MMX(Pixel *out, Pixel **in_table, PixDim w) {
  945.     static const __int64 x0002000200020002 = 0x0002000200020002i64;
  946.     __asm {
  947.         push        ebp
  948.         push        esi
  949.         push        edi
  950.         push        ebx
  951.  
  952.         mov            ebp,[esp + 12 + 16]        ;ebp = pixel counter
  953.         shl            ebp,2
  954.         neg            ebp
  955.         mov            edi,[esp + 4 + 16]        ;edi = destination pointer
  956.  
  957.         ;load row pointers!
  958.  
  959.         mov            esi,[esp + 8 + 16]        ;esi = row pointer table
  960.  
  961.         mov            eax,[esi+4]
  962.         mov            ebx,[esi+8]
  963.         mov            ecx,[esi+12]
  964.  
  965.         and            ebp,0fffffff8h
  966.         jz            oddpixelcheck
  967.  
  968.         sub            eax,ebp
  969.         sub            ebx,ebp
  970.         sub            ecx,ebp
  971.         sub            edi,ebp
  972.         movq        mm6,x0002000200020002
  973.         pxor        mm7,mm7
  974.  
  975. pixelloop:
  976.         movq        mm0,[eax+ebp]
  977.  
  978.         movq        mm1,[ebx+ebp]
  979.         movq        mm3,mm0
  980.  
  981.         movq        mm2,[ecx+ebp]
  982.         punpcklbw    mm0,mm7
  983.  
  984.         movq        mm4,mm1
  985.         punpckhbw    mm3,mm7
  986.  
  987.         movq        mm5,mm2
  988.         punpcklbw    mm1,mm7
  989.  
  990.         punpckhbw    mm4,mm7
  991.         paddw        mm1,mm1
  992.  
  993.         punpcklbw    mm2,mm7
  994.         paddw        mm4,mm4
  995.  
  996.         punpckhbw    mm5,mm7
  997.         paddw        mm0,mm2
  998.  
  999.         paddw        mm3,mm5
  1000.         paddw        mm1,mm6
  1001.  
  1002.         paddw        mm4,mm6
  1003.         paddw        mm1,mm0
  1004.  
  1005.         paddw        mm4,mm3
  1006.         psraw        mm1,2
  1007.  
  1008.         psraw        mm4,2
  1009.         add            ebp,8
  1010.  
  1011.         packuswb    mm1,mm4
  1012.  
  1013.         movq        [edi+ebp-8],mm1
  1014.         jne            pixelloop
  1015.  
  1016. oddpixelcheck:
  1017.         test        dword ptr [esp+12+16],1
  1018.         jz            xit
  1019.  
  1020.         movd        mm0,[eax]
  1021.  
  1022.         movd        mm1,[ebx]
  1023.         punpcklbw    mm0,mm7
  1024.         movd        mm2,[ecx]
  1025.         punpcklbw    mm1,mm7
  1026.  
  1027.         punpcklbw    mm2,mm7
  1028.         paddw        mm1,mm1
  1029.  
  1030.         paddw        mm0,mm2
  1031.         paddw        mm1,mm6
  1032.  
  1033.         paddw        mm1,mm0
  1034.  
  1035.         psraw        mm1,2
  1036.  
  1037.         packuswb    mm1,mm1
  1038.  
  1039.         movd        [edi],mm1
  1040.  
  1041. xit:
  1042.         pop            ebx
  1043.         pop            edi
  1044.         pop            esi
  1045.         pop            ebp
  1046.  
  1047.         ret
  1048.     }
  1049. }
  1050.  
  1051. static long __declspec(naked) resize_table_col_by2cubic_MMX(Pixel *out, Pixel **in_table, PixDim w) {
  1052.     static const __int64 x0004000400040004 = 0x0004000400040004i64;
  1053.     __asm {
  1054.         push        ebp
  1055.         push        esi
  1056.         push        edi
  1057.         push        edx
  1058.         push        ecx
  1059.         push        ebx
  1060.  
  1061.         mov            ebp,[esp + 12 + 24]        ;ebp = pixel counter
  1062.         shl            ebp,2
  1063.         neg            ebp
  1064.         mov            edi,[esp + 4 + 24]        ;edi = destination pointer
  1065.  
  1066.         ;load row pointers!
  1067.  
  1068.         mov            esi,[esp + 8 + 24]        ;esi = row pointer table
  1069.  
  1070.         mov            eax,[esi+4]
  1071.         mov            ebx,[esi+12]
  1072.         mov            ecx,[esi+16]
  1073.         mov            edx,[esi+20]
  1074.         mov            esi,[esi+24]
  1075.  
  1076.         sub            eax,ebp
  1077.         sub            ebx,ebp
  1078.         sub            ecx,ebp
  1079.         sub            edx,ebp
  1080.         sub            esi,ebp
  1081.         sub            edi,ebp
  1082.         movq        mm6,x0004000400040004
  1083.         pxor        mm7,mm7
  1084.  
  1085. pixelloop:
  1086.         movd        mm0,[eax+ebp]
  1087.  
  1088.         movd        mm1,[ebx+ebp]
  1089.         punpcklbw    mm0,mm7
  1090.         movd        mm2,[ecx+ebp]
  1091.         punpcklbw    mm1,mm7
  1092.         movd        mm3,[edx+ebp]
  1093.         punpcklbw    mm2,mm7
  1094.         movd        mm4,[esi+ebp]
  1095.         punpcklbw    mm3,mm7
  1096.  
  1097.         punpcklbw    mm4,mm7
  1098.         paddw        mm1,mm3
  1099.  
  1100.         movq        mm3,mm1
  1101.         psllw        mm1,2
  1102.  
  1103.         paddw        mm0,mm4
  1104.         psllw        mm2,3
  1105.  
  1106.         paddw        mm1,mm3
  1107.         paddw        mm2,mm6
  1108.  
  1109.         psubw        mm2,mm0
  1110.         paddw        mm2,mm1
  1111.  
  1112.         psraw        mm2,4
  1113.  
  1114.         packuswb    mm2,mm2
  1115.         add            ebp,4
  1116.         movd        [edi+ebp-4],mm2
  1117.         jne            pixelloop
  1118.  
  1119.         pop            ebx
  1120.         pop            ecx
  1121.         pop            edx
  1122.         pop            edi
  1123.         pop            esi
  1124.         pop            ebp
  1125.  
  1126.         ret
  1127.     }
  1128. }
  1129.  
  1130. static void resize_table_col(Pixel *out, Pixel **in_rows, int *filter, int filter_width, PixDim w, long frac, int accel_code) {
  1131.     int x;
  1132.  
  1133.     if (MMX_enabled) {
  1134.         PROFILE_START
  1135.  
  1136.         if (accel_code == ACCEL_BICUBICBY2)
  1137.             resize_table_col_by2cubic_MMX(out, in_rows, w);
  1138.         else if (accel_code == ACCEL_BILINEARBY2)
  1139.             resize_table_col_by2linear_MMX(out, in_rows, w);
  1140.         else
  1141.             resize_table_col_MMX(out, in_rows, filter, filter_width, w, frac);
  1142.  
  1143.         PROFILE_ADD(column)
  1144.  
  1145.         return;
  1146.     }
  1147.  
  1148.     x = 0;
  1149.     do {
  1150.         int x2, r, g, b;
  1151.         Pixel **in_row;
  1152.         int *filter2;
  1153.  
  1154.         x2 = filter_width;
  1155.         in_row = in_rows;
  1156.         filter2 = filter + frac*filter_width;
  1157.         r = g = b = 0;
  1158.         do {
  1159.             Pixel c;
  1160.             int a;
  1161.  
  1162.             c =  (*in_row++)[x];
  1163.             a = *filter2++;
  1164.  
  1165.             r += ((c>>16)&255) * a;
  1166.             g += ((c>> 8)&255) * a;
  1167.             b += ((c    )&255) * a;
  1168.  
  1169.         } while(--x2);
  1170.  
  1171.         r = (r + 8192)>>14;
  1172.         g = (g + 8192)>>14;
  1173.         b = (b + 8192)>>14;
  1174.  
  1175.         if (r<0) r=0; else if (r>255) r=255;
  1176.         if (g<0) g=0; else if (g>255) g=255;
  1177.         if (b<0) b=0; else if (b>255) b=255;
  1178.  
  1179.         *out++ = (r<<16) + (g<<8) + b;
  1180.     } while(++x < w);
  1181. }
  1182.  
  1183.  
  1184. #define RED(x) ((signed long)((x)>>16)&255)
  1185. #define GRN(x) ((signed long)((x)>> 8)&255)
  1186. #define BLU(x) ((signed long)(x)&255)
  1187.  
  1188. #if 0
  1189. #if 0
  1190. static inline long cerpclip(long y1, long y2, long y3, long y4, long d) {
  1191.     // floating-point:    y2 + d((y3-y1) + d((2y1-2y2+y3-y4) + d(-y1+y2-y3+y4)))
  1192.     // fixed-point:        (256*y2 + d((65536*(y3-y1) + d(256*(2y1-2y2+y3-y4) + d(-y1+y2-y3+y4)))>>16))>>8
  1193.  
  1194.     long t = 65536*y2 + d*((65536*(y3-y1) + d*(256*(2*y1-2*y2+y3-y4) + d*(-y1+y2-y3+y4)))>>8);
  1195.  
  1196.     return t<0 ? 0 : t>0xFFFFFF ? 0xFFFFFF : t;
  1197. //    return d<<16;//(y2*(256-d)+y3*d)<<8;
  1198. }
  1199. #else
  1200. static inline long cerpclip(long y1, long y2, long y3, long y4, long d) {
  1201.     //    65536*y2 + d*((65536*(y3-y1) + d*(256*(2*y1-2*y2+y3-y4) + d*(-y1+y2-y3+y4)))>>8);
  1202.  
  1203.     //    t1 = y1-y2;
  1204.     //    t2 = t1+y3-y4;
  1205.     //    res = 65536*y2 + d*((65536*(y3-y1) + d*(256*(t1+t2) - d*t2))>>8);
  1206.     __asm {
  1207.         mov        eax,y1
  1208.         mov        ebx,y3
  1209.  
  1210.         sub        eax,y2        ;eax = t1
  1211.         sub        ebx,y4
  1212.  
  1213.         add        ebx,eax        ;ebx = t2
  1214.         mov        ecx,d        ;ecx = d
  1215.  
  1216.         add        eax,ebx        ;eax = t1+t2
  1217.         mov        edx,y3        ;edx = y3
  1218.  
  1219.         imul    ecx,ebx        ;ecx = d*t2
  1220.  
  1221.         shl        eax,8        ;eax = 256*(t1+t2)
  1222.         mov        ebx,y1        ;ebx = y1
  1223.  
  1224.         sub        edx,ebx        ;edx = y3-y1
  1225.         sub        eax,ecx        ;eax = 256*(t1+t2) - d*t2
  1226.  
  1227.         imul    eax,d        ;eax = d*(256*(t1+t2) - d*t2)
  1228.  
  1229.         shl        edx,16        ;edx = 65536*(y3-y1)
  1230.         mov        ecx,y2        ;ecx = y2
  1231.  
  1232.         shl        ecx,16        ;ecx = 65536*y2
  1233.         add        eax,edx        ;eax = 65536*(y3-y1) + d*(256*(t1+t2) - d*t2)
  1234.  
  1235.         sar        eax,8        ;eax = (65536*(y3-y1) + d*(256*(t1+t2) - d*t2))>>8
  1236.         mov        edx,16777215
  1237.  
  1238.         imul    eax,d        ;eax = d*((65536*(y3-y1) + d*(256*(t1+t2) - d*t2))>>8)
  1239.  
  1240.         add        eax,ecx        ;eax = 65536*y2 + d*((65536*(y3-y1) + d*(256*(t1+t2) - d*t2))>>8);
  1241.         mov        ecx,80000000h
  1242.  
  1243.         add        ecx,eax        ;ecx is negative if eax is okay, positive if not
  1244.         sub        edx,eax        ;set carry if eax > FFFFFF
  1245.  
  1246.         sar        edx,31
  1247.  
  1248.         sar        ecx,31
  1249.         and        edx,00FFFFFFh
  1250.  
  1251.         and        eax,ecx
  1252.  
  1253.         or        eax,edx        ;if eax>FFFFFF, clamp at FFFFFFFF
  1254.  
  1255.     }
  1256. }
  1257. #endif
  1258.  
  1259. static inline Pixel cc(Pixel y1, Pixel y2, Pixel y3, Pixel y4, long d) {
  1260.     long red, grn, blu;
  1261.  
  1262.     red = cerpclip(RED(y1),RED(y2),RED(y3),RED(y4),d);
  1263.  
  1264. //    if (red<0) red=0; else if (red>16777215) red=16777215;
  1265. //    if (red<0) red=0;
  1266. //    if (red>16777215) red=16777215;
  1267.  
  1268.     grn = cerpclip(GRN(y1),GRN(y2),GRN(y3),GRN(y4),d);
  1269.  
  1270. //    if (grn<0) grn=0; else if (grn>16777215) grn=16777215;
  1271. //    if (grn<0) grn=0;
  1272. //    if (grn>16777215) grn=16777215;
  1273.  
  1274.     blu = cerpclip(BLU(y1),BLU(y2),BLU(y3),BLU(y4),d);
  1275.  
  1276. //    if (blu<0) blu=0; else if (blu>16777215) blu=16777215;
  1277. //    if (blu<0) blu=0;
  1278. //    if (blu>16777215) blu=16777215;
  1279.  
  1280.     return (red & 0xFF0000) | ((grn>>8) & 0x00FF00) | (blu>>16);
  1281. }
  1282. #else
  1283. static inline Pixel cc(const Pixel *yptr, const int *tbl) {
  1284.     const Pixel y1 = yptr[0];
  1285.     const Pixel y2 = yptr[1];
  1286.     const Pixel y3 = yptr[2];
  1287.     const Pixel y4 = yptr[3];
  1288.     long red, grn, blu;
  1289.  
  1290.     red = RED(y1)*tbl[0] + RED(y2)*tbl[1] + RED(y3)*tbl[2] + RED(y4)*tbl[3];
  1291.     grn = GRN(y1)*tbl[0] + GRN(y2)*tbl[1] + GRN(y3)*tbl[2] + GRN(y4)*tbl[3];
  1292.     blu = BLU(y1)*tbl[0] + BLU(y2)*tbl[1] + BLU(y3)*tbl[2] + BLU(y4)*tbl[3];
  1293.  
  1294.     if (red<0) red=0; else if (red>4194303) red=4194303;
  1295.     if (grn<0) grn=0; else if (grn>4194303) grn=4194303;
  1296.     if (blu<0) blu=0; else if (blu>4194303) blu=4194303;
  1297.  
  1298.     return ((red<<2) & 0xFF0000) | ((grn>>6) & 0x00FF00) | (blu>>14);
  1299. }
  1300. static inline Pixel cc2(Pixel y1, Pixel y2, Pixel y3, Pixel y4, const int *tbl) {
  1301.     long red, grn, blu;
  1302.  
  1303.     red = RED(y1)*tbl[0] + RED(y2)*tbl[1] + RED(y3)*tbl[2] + RED(y4)*tbl[3];
  1304.     grn = GRN(y1)*tbl[0] + GRN(y2)*tbl[1] + GRN(y3)*tbl[2] + GRN(y4)*tbl[3];
  1305.     blu = BLU(y1)*tbl[0] + BLU(y2)*tbl[1] + BLU(y3)*tbl[2] + BLU(y4)*tbl[3];
  1306.  
  1307.     if (red<0) red=0; else if (red>4194303) red=4194303;
  1308.     if (grn<0) grn=0; else if (grn>4194303) grn=4194303;
  1309.     if (blu<0) blu=0; else if (blu>4194303) blu=4194303;
  1310.  
  1311.     return ((red<<2) & 0xFF0000) | ((grn>>6) & 0x00FF00) | (blu>>14);
  1312. }
  1313. #endif
  1314.  
  1315. #undef RED
  1316. #undef GRN
  1317. #undef BLU
  1318.  
  1319. #if 1
  1320. static void cc_row(Pixel *dst, Pixel *src, long w, long xs_left, long xs_right, long xaccum, long xinc, int *table) {
  1321.  
  1322.     src += xaccum>>16;
  1323.     xaccum&=0xffff;
  1324.  
  1325.     if (xs_left) {
  1326.         Pixel x[4] = { src[0], src[0], src[1], src[2] };
  1327.  
  1328.         do {
  1329.             *dst++ = cc(x, table + 4*((xaccum>>8)&0xff));
  1330.  
  1331.             xaccum += xinc;
  1332.             src += xaccum>>16;
  1333.             xaccum&=0xffff;
  1334.         } while(--xs_left);
  1335.     }
  1336.  
  1337.     if (!MMX_enabled) {
  1338.         do {
  1339.             *dst++ = cc(src-1, table + 4*((xaccum>>8)&0xff));
  1340.  
  1341.             xaccum += xinc;
  1342.             src += xaccum>>16;
  1343.             xaccum&=0xffff;
  1344.         } while(--w);
  1345.     } else {
  1346.         asm_resize_ccint(dst, src-1, src, src+1, src+2, w, xaccum, xinc, table+1024);
  1347.  
  1348.         dst += w;
  1349.  
  1350.         xaccum += xinc*w;
  1351.         src += xaccum>>16;
  1352.         xaccum &= 0xffff;
  1353.     }
  1354.  
  1355.     if (xs_right) do {
  1356.         Pixel x[4] = { src[-1], src[0], src[1], src[1] };
  1357.  
  1358.         *dst++ = cc(x, table + 4*((xaccum>>8)&0xff));
  1359.  
  1360.         xaccum += xinc;
  1361.         src += xaccum>>16;
  1362.         xaccum&=0xffff;
  1363.     } while(--xs_right);
  1364. }
  1365. #else
  1366. static void cc_row(Pixel *dst, Pixel *src, long w, long xs_left, long xs_right, long xaccum, long xinc) {
  1367.  
  1368.     src += xaccum>>16;
  1369.     xaccum&=0xffff;
  1370.  
  1371.     if (xs_left) do {
  1372.         *dst++ = cc(src[0], src[0], src[1], src[2], (xaccum>>8)&0xff);
  1373.  
  1374.         xaccum += xinc;
  1375.         src += xaccum>>16;
  1376.         xaccum&=0xffff;
  1377.     } while(--xs_left);
  1378.  
  1379.     if (!MMX_enabled) {
  1380.         do {
  1381.             *dst++ = cc(src[-1],src[0],src[1],src[2],(xaccum>>8)&0xff);
  1382.  
  1383.             xaccum += xinc;
  1384.             src += xaccum>>16;
  1385.             xaccum&=0xffff;
  1386.         } while(--w);
  1387.     } else {
  1388.         asm_resize_ccint(dst, src-1, src, src+1, src+2, w, xaccum, xinc+1024);
  1389.  
  1390.         dst += w;
  1391.  
  1392.         xaccum += xinc*w;
  1393.         src += xaccum>>16;
  1394.         xaccum &= 0xffff;
  1395.     }
  1396.  
  1397.     if (xs_right) do {
  1398.         *dst++ = cc(src[-1], src[0], src[1], src[1], (xaccum>>8)&0xff);
  1399.  
  1400.         xaccum += xinc;
  1401.         src += xaccum>>16;
  1402.         xaccum&=0xffff;
  1403.     } while(--xs_right);
  1404. }
  1405. #endif
  1406.  
  1407. static void bc_row(Pixel *dst, Pixel *src, long w, long xs_left, long xs_right, long xaccum, long xinc) {
  1408.  
  1409.     if (xs_left) do {
  1410.         *dst++ = *src;
  1411.     } while(--xs_left);
  1412.  
  1413.     src += xaccum>>16;
  1414.     xaccum&=0xffff;
  1415.  
  1416.     asm_resize_interp_row_run(dst, src, w, xaccum, xinc);
  1417.  
  1418.     dst += w;
  1419.  
  1420.     xaccum += xinc*w;
  1421.     src += xaccum>>16;
  1422.     xaccum &= 0xffff;
  1423.  
  1424.     if (xs_right) do {
  1425.         *dst++ = *src;
  1426.     } while(--xs_right);
  1427. }
  1428.  
  1429. //#pragma optimize("",off);
  1430.  
  1431. // Conditions we need to handle:
  1432. //
  1433. //    0x20000 (interpolation): offset should be 0x8000
  1434.  
  1435. long accum_start(long inc) {
  1436.  
  1437.     if (inc >= 0x10000) {
  1438.         inc &= 0xffff;
  1439.  
  1440.         if (!inc) inc = 0x10000;
  1441.  
  1442.         return inc/2;
  1443.     } else
  1444.         return 0;
  1445. }
  1446.  
  1447. static int resize_table(MyFilterData *mfd ,VBitmap *source, VBitmap *dest, Pixel *dst) {
  1448.  
  1449.     PixDim dstw = mfd->new_x;
  1450.     PixDim dsth = mfd->new_y;
  1451.     PixDim w = dstw;
  1452.     PixDim h = dsth;
  1453.     Pixel *src;
  1454.  
  1455.     long    x_accum=0, x_inc;
  1456.     long    y_accum=0, y_inc;
  1457.     PixDim w_left, w_right, w_mid;
  1458.     int row = 0;
  1459.     int y = 0;
  1460.     int accel_col = 0, accel_row = 0;
  1461.  
  1462.     x_inc = (source->w<<16) / dstw;
  1463.     y_inc = (source->h<<16) / dsth;
  1464.     src = source->data;
  1465.  
  1466.     if (mfd->filter_mode == FILTER_TABLEBICUBIC && y_inc == 0x20000L)
  1467.         accel_col = ACCEL_BICUBICBY2;
  1468.  
  1469.     if (mfd->filter_mode == FILTER_TABLEBILINEAR && y_inc == 0x20000L)
  1470.         accel_col = ACCEL_BILINEARBY2;
  1471.  
  1472.     if (mfd->filter_mode == FILTER_TABLEBICUBIC && x_inc == 0x20000L)
  1473.         accel_row = ACCEL_BICUBICBY2;
  1474.  
  1475.     if (mfd->filter_mode == FILTER_TABLEBILINEAR && x_inc == 0x20000L)
  1476.         accel_row = ACCEL_BILINEARBY2;
  1477.  
  1478.     if (mfd->x_table) {
  1479.         w_left = (0x10000 * ((mfd->x_filtwidth - 2)>>1) + x_inc-1)/x_inc;
  1480.         w_right = w_left;
  1481.     } else if (mfd->filter_mode == FILTER_TABLEBICUBIC) {
  1482.         long xt;
  1483.  
  1484.         x_accum = accum_start(x_inc);
  1485.  
  1486.         // Determine the 3 x segments (l, m, r)
  1487.         //
  1488.         // left: number of increments it takes to get to the 2nd pixel
  1489.  
  1490.         if (x_accum >= 0x10000L)
  1491.             w_left = 0;
  1492.         else
  1493.             w_left = (0xFFFF + x_inc - x_accum) / x_inc;
  1494.  
  1495.         // right: number of increments from (width-1) to expected last value, rounded up
  1496.  
  1497.         xt = x_accum + w*x_inc;
  1498.         if (xt >= (source->w-1)*0x10000)
  1499.             w_right = (xt - (source->w-1)*0x10000) / x_inc + 1;
  1500.         else
  1501.             w_right = 0;
  1502.  
  1503.     } else {
  1504.         long xt;
  1505.  
  1506.         x_accum = accum_start(x_inc);
  1507.  
  1508.         w_left = 0;
  1509.  
  1510.         // right: number of increments from (width) to expected last value, rounded up
  1511.  
  1512.         xt = x_accum + w*x_inc;
  1513.         if (xt >= source->w*0x10000)
  1514.             w_right = (xt - source->w*0x10000) / x_inc + 1;
  1515.         else
  1516.             w_right = 0;
  1517.     }
  1518.  
  1519.     w_mid = w - w_left - w_right;
  1520.  
  1521.     {
  1522.         int prefill = mfd->y_filtwidth/2 - 1;
  1523.         int i;
  1524.  
  1525.  
  1526.         for(i=prefill; i<mfd->y_filtwidth; i++) {
  1527.             if (mfd->x_table)
  1528.                 resize_table_row(mfd->row_table[i], src, mfd->x_table, mfd->x_filtwidth, w_mid, w_left, w_right, source->w, 0, x_inc, accel_row);
  1529.             else if (mfd->filter_mode == FILTER_TABLEBICUBIC)
  1530.                 cc_row(mfd->row_table[i], src, w_mid, w_left, w_right, x_accum, x_inc, mfd->cubic4_tbl);
  1531.             else
  1532.                 bc_row(mfd->row_table[i], src, w_mid, w_left, w_right, x_accum, x_inc);
  1533.  
  1534.             src = (Pixel *)((char *)src + source->pitch);
  1535.             ++y;
  1536.         }
  1537.  
  1538.         for(i=0; i<prefill; i++)
  1539.             memcpy(mfd->row_table[i], mfd->row_table[prefill], sizeof(Pixel)*dstw);
  1540.     }
  1541.  
  1542.     do {
  1543.         if (mfd->y_table)
  1544.             resize_table_col(dst, mfd->row_table + row, mfd->y_table, mfd->y_filtwidth, w, (y_accum>>8)&255, accel_col);
  1545.         else if (mfd->filter_mode == FILTER_TABLEBICUBIC) {
  1546.             int row2;
  1547.  
  1548.             row2 = (row - 4)&3;
  1549.  
  1550.             if (MMX_enabled)
  1551.                 asm_resize_ccint_col(dst, mfd->row_table[row2], mfd->row_table[row2+1], mfd->row_table[row2+2], mfd->row_table[row2+3], w, mfd->cubic4_tbl+1024+4*((y_accum>>8)&0xff));
  1552.             else {
  1553.                 Pixel32 *dst2 = dst;
  1554.                 int x = 0;
  1555.  
  1556.                 do {
  1557.                     *dst2++ = cc2(mfd->row_table[row2+0][x], mfd->row_table[row2+1][x], mfd->row_table[row2+2][x], mfd->row_table[row2+3][x], mfd->cubic4_tbl + 4*((y_accum>>8)&0xff));
  1558.                 } while(++x < w);
  1559.             }
  1560.         } else {
  1561.             asm_resize_interp_col_run(
  1562.                     dst,
  1563.                     mfd->row_table[row],
  1564.                     mfd->row_table[row^1],
  1565.                     w,
  1566.                     y_accum);
  1567.  
  1568.         }
  1569.  
  1570.         y_accum += y_inc;
  1571.  
  1572.         while(y_accum >= 0x10000) {
  1573.             if (y < source->h)
  1574.                 if (mfd->x_table)
  1575.                     resize_table_row(mfd->row_table[row], src, mfd->x_table, mfd->x_filtwidth, w_mid, w_left, w_right, source->w, 0, x_inc, accel_row);
  1576.                 else if (mfd->filter_mode == FILTER_TABLEBICUBIC)
  1577.                     cc_row(mfd->row_table[row], src, w_mid, w_left, w_right, x_accum, x_inc, mfd->cubic4_tbl);
  1578.                 else
  1579.                     bc_row(mfd->row_table[row], src, w_mid, w_left, w_right, x_accum, x_inc);
  1580.             else
  1581.                 memcpy(mfd->row_table[row], mfd->row_table[row ? row-1 : mfd->y_filtwidth-1], dstw*sizeof(Pixel));
  1582.  
  1583.             src = (Pixel *)((char *)src + source->pitch);
  1584.  
  1585.             ++y;
  1586.             y_accum -= 0x10000;
  1587.             if (++row >= mfd->y_filtwidth)
  1588.                 row = 0;
  1589.         }
  1590.  
  1591.         dst = (Pixel *)((char *)dst + dest->pitch);
  1592.     } while(--h);
  1593.  
  1594.     if (MMX_enabled)
  1595.         __asm emms
  1596.  
  1597.     return 0;
  1598. }
  1599.  
  1600. int resize_run(MyFilterData *mfd, VBitmap *source, VBitmap *dest) {
  1601.  
  1602.     unsigned long x_inc, y_inc;
  1603.     long dstw = mfd->new_x;
  1604.     long dsth = mfd->new_y;
  1605.     long h_margin=0, w_margin=0;
  1606.     Pixel *dst, *src;
  1607.  
  1608.     dst = dest->data;
  1609.     src = source->data;
  1610.  
  1611.     // Draw letterbox bound
  1612.  
  1613.     if (mfd->fLetterbox) {
  1614.         Pixel *dst2 = dst, *dst3;
  1615.         Pixel fill = revcolor(mfd->rgbColor);
  1616.  
  1617.         long w1, w2, w, h;
  1618.  
  1619.         w_margin = dest->w - mfd->new_x;
  1620.         h_margin = dest->h - mfd->new_y;
  1621.  
  1622.         if (w_margin < 0)
  1623.             w_margin = 0;
  1624.  
  1625.         if (h_margin < 0)
  1626.             h_margin = 0;
  1627.  
  1628.         h = h_margin/2;
  1629.         if (h>0) do {
  1630.             dst3  = dst2;
  1631.             w = dest->w;
  1632.             do {
  1633.                 *dst3++ = fill;
  1634.             } while(--w);
  1635.  
  1636.             dst2 = (Pixel32 *)((char *)dst2 + dest->pitch);
  1637.         } while(--h);
  1638.  
  1639.         w1 = w_margin/2;
  1640.         w2 = w_margin - w_margin/2;
  1641.  
  1642.         h = mfd->new_y;
  1643.         do {
  1644.             dst3 = dst2;
  1645.  
  1646.             // fill left
  1647.  
  1648.             w = w1;
  1649.             if (w) do {
  1650.                 *dst3++ = fill;
  1651.             } while(--w);
  1652.  
  1653.             // skip center
  1654.  
  1655.             dst3 += mfd->new_x;
  1656.  
  1657.             // fill right
  1658.  
  1659.             w = w2;
  1660.             if (w) do {
  1661.                 *dst3++ = fill;
  1662.             } while(--w);
  1663.  
  1664.  
  1665.             dst2 = (Pixel32 *)((char *)dst2 + dest->pitch);
  1666.         } while(--h);
  1667.  
  1668.         h = h_margin - h_margin/2;
  1669.         if (h>0) do {
  1670.             dst3  = dst2;
  1671.             w = dest->w;
  1672.             do {
  1673.                 *dst3++ = fill;
  1674.             } while(--w);
  1675.  
  1676.             dst2 = (Pixel32 *)((char *)dst2 + dest->pitch);
  1677.         } while(--h);
  1678.  
  1679.         // offset resampled rectangle
  1680.  
  1681.         dst = (Pixel *)((char *)dst + dest->pitch * (h_margin/2)) + (w_margin/2);
  1682.     }
  1683.  
  1684.     // Compute parameters
  1685.  
  1686.     if (dstw >= source->w)
  1687.         x_inc = MulDivTrunc(source->w-1, 0x10000L, dstw-1);
  1688.     else
  1689.         x_inc = MulDivTrunc(source->w, 0x10000L, dstw);
  1690.  
  1691.     if (dsth >= source->h)
  1692.         y_inc = MulDivTrunc(source->h-1, 0x10000L, dsth-1);
  1693.     else
  1694.         y_inc = MulDivTrunc(source->h, 0x10000L, dsth);
  1695.  
  1696.     switch(mfd->filter_mode) {
  1697.     case FILTER_BICUBIC:
  1698.         {
  1699.             long x_accum, y_accum, y_frac, xt;
  1700.             long w,h,max_h,x_left, x_right, x_mid;
  1701.             long width = dstw;
  1702.             Pixel *rsrc;
  1703.             int row_rotate=0;
  1704.  
  1705.             x_accum = accum_start(x_inc);
  1706.             y_accum = accum_start(y_inc);
  1707.  
  1708.             // Determine the 3 x segments (l, m, r)
  1709.             //
  1710.             // left: number of increments it takes to get to the 2nd pixel
  1711.  
  1712.             if (x_accum >= 0x10000L)
  1713.                 x_left = 0;
  1714.             else
  1715. //                x_left = (0xFFFF + x_inc - (x_inc/2)) / x_inc;
  1716.                 x_left = (0xFFFF + x_inc - x_accum) / x_inc;
  1717.  
  1718.             // right: number of increments from (width-1) to expected last value, rounded up
  1719.  
  1720.             xt = x_accum + width*x_inc;
  1721.             if (xt >= (source->w-1)*0x10000)
  1722.                 x_right = (xt - (source->w-1)*0x10000) / x_inc + 1;
  1723.             else
  1724.                 x_right = 0;
  1725.  
  1726.             x_mid = width - x_left - x_right;
  1727.  
  1728.             _ASSERT(x_left>=0);
  1729.             _ASSERT(x_right>=0);
  1730.             _ASSERT(x_mid>=0);
  1731.  
  1732.             // make sure our left and right values won't cause crashes
  1733.  
  1734.             _ASSERT(x_accum + x_left * x_inc >= 0x10000);
  1735.             _ASSERT(x_accum + (x_left+x_mid)*x_inc < (source->w-1)*0x10000);
  1736.  
  1737.             // make sure our left and right values are optimal
  1738.  
  1739.             _ASSERT(!x_left || x_accum + (x_left-1)*x_inc < 0x10000);
  1740.             _ASSERT(!x_right || !x_mid || x_accum + (x_left+x_mid+1)*x_inc >= (source->w-1)*0x10000);
  1741.  
  1742.             // Compute first 4 cubic rows
  1743.  
  1744.             cc_row(mfd->cubic_rows + 0*width, (Pixel *)((char *)src + (y_accum>=0x10000 ? -1 : 0)*source->pitch), x_mid, x_left, x_right, x_accum, x_inc, mfd->cubic4_tbl);
  1745.             cc_row(mfd->cubic_rows + 1*width, (Pixel *)((char *)src +  0*source->pitch), x_mid, x_left, x_right, x_accum, x_inc, mfd->cubic4_tbl);
  1746.             cc_row(mfd->cubic_rows + 2*width, (Pixel *)((char *)src +  1*source->pitch), x_mid, x_left, x_right, x_accum, x_inc, mfd->cubic4_tbl);
  1747.             cc_row(mfd->cubic_rows + 3*width, (Pixel *)((char *)src +  2*source->pitch), x_mid, x_left, x_right, x_accum, x_inc, mfd->cubic4_tbl);
  1748.  
  1749.             // max_h = (number of increments to get y to [height-1])
  1750.  
  1751.             max_h = (y_accum + (source->h-1)*0x10000L + y_inc-1 ) / y_inc - 1;
  1752.  
  1753.             _ASSERT(max_h>=0);
  1754.  
  1755.             src = (Pixel *)((char *)src + (y_accum>>16) * source->pitch);
  1756.             y_accum &= 0xffff;
  1757.  
  1758.             // Start the cubic!
  1759.  
  1760.             h = dsth;
  1761.             do {
  1762.                 y_frac = ((y_accum>>8)&255);
  1763.                 const int *co_ptr = mfd->cubic4_tbl + 4*y_frac;
  1764.                 rsrc = mfd->cubic_rows;
  1765.  
  1766.                 w = dstw;
  1767.  
  1768.                 if (!MMX_enabled) {
  1769.                     switch(row_rotate) {
  1770.                     case 0:
  1771.                         do {
  1772.  
  1773.     //    CODEGEN ERROR!    *dst++ = cc(rsrc[0], rsrc[width], rsrc[2*width], rsrc[3*width], y_frac);
  1774.     //
  1775.     //    Causes VC++ 6.0 in Release mode to push the same argument for rsrc[width] and rsrc[2*width]
  1776.  
  1777.                             Pixel *row1 = rsrc + width;
  1778.                             Pixel *row2 = row1 + width;
  1779.                             Pixel *row3 = row2 + width;
  1780.  
  1781.                             *dst++ = cc2(*rsrc, *row1, *row2, *row3, co_ptr);
  1782.  
  1783.                             ++rsrc;
  1784.                         } while(--w);
  1785.                         break;
  1786.                     case 1:
  1787.                         do {
  1788.                             Pixel *row1 = rsrc + width;
  1789.                             Pixel *row2 = row1 + width;
  1790.                             Pixel *row3 = row2 + width;
  1791.  
  1792.                             *dst++ = cc2(*row1, *row2, *row3, *rsrc, co_ptr);
  1793.  
  1794.                             ++rsrc;
  1795.                         } while(--w);
  1796.                         break;
  1797.                     case 2:
  1798.                         do {
  1799.                             Pixel *row1 = rsrc + width;
  1800.                             Pixel *row2 = row1 + width;
  1801.                             Pixel *row3 = row2 + width;
  1802.  
  1803.                             *dst++ = cc2(*row2, *row3, *rsrc, *row1, co_ptr);
  1804.  
  1805.                             ++rsrc;
  1806.                         } while(--w);
  1807.                         break;
  1808.                     case 3:
  1809.                         do {
  1810.                             Pixel *row1 = rsrc + width;
  1811.                             Pixel *row2 = row1 + width;
  1812.                             Pixel *row3 = row2 + width;
  1813.  
  1814.                             *dst++ = cc2(*row3, *rsrc, *row1, *row2, co_ptr);
  1815.  
  1816.                             ++rsrc;
  1817.                         } while(--w);
  1818.                         break;
  1819.                     }
  1820. //                    dst = (Pixel *)((char *)dst + dest->modulo);
  1821.                     dst = (Pixel *)((char *)(dst-dstw) + dest->pitch);
  1822.                 } else {
  1823.                     switch(row_rotate) {
  1824.                     case 0:
  1825.                         asm_resize_ccint_col(dst, rsrc, rsrc+width, rsrc+2*width, rsrc+3*width, w, co_ptr + 1024);
  1826.                         break;
  1827.                     case 1:
  1828.                         asm_resize_ccint_col(dst, rsrc+width, rsrc+2*width, rsrc+3*width, rsrc, w, co_ptr + 1024);
  1829.                         break;
  1830.                     case 2:
  1831.                         asm_resize_ccint_col(dst, rsrc+2*width, rsrc+3*width, rsrc, rsrc+width, w, co_ptr + 1024);
  1832.                         break;
  1833.                     case 3:
  1834.                         asm_resize_ccint_col(dst, rsrc+3*width, rsrc, rsrc+width, rsrc+2*width, w, co_ptr + 1024);
  1835.                         break;
  1836.                     }
  1837.                     dst = (Pixel *)((char *)dst + dest->pitch);
  1838.                 }
  1839.  
  1840.                 y_accum += y_inc;
  1841.                 if (y_accum>>16) {
  1842.                     int yd = y_accum>>16;
  1843.                     Pixel *rsrc, *rdst;
  1844.  
  1845.                     src = (Pixel *)((char *)src + yd * source->pitch);
  1846.                     y_accum &= 0xffff;
  1847.  
  1848. //                    if (yd<4) {
  1849. //                        memmove(mfd->cubic_rows, mfd->cubic_rows + width*yd, sizeof(Pixel)*width*(4-yd));
  1850. //                    } else {
  1851. //                        yd = 4;
  1852. //                    }
  1853.                     if (yd>4) yd=4;
  1854.  
  1855.                     // If we're scaling down, we don't want to run off the bottom of the
  1856.                     // bitmap.
  1857.  
  1858.                     if (max_h > 0) {
  1859.                         --max_h;
  1860.  
  1861.                         rsrc = (Pixel *)((char *)src + source->pitch * (3-yd));
  1862.                         while(yd--) {
  1863.                             rdst = mfd->cubic_rows + width*row_rotate;
  1864.                             cc_row(rdst, rsrc, x_mid, x_left, x_right, accum_start(x_inc), x_inc, mfd->cubic4_tbl);
  1865.                             row_rotate = (row_rotate+1) & 3;
  1866.                             rsrc = (Pixel *)((char *)rsrc + source->pitch);
  1867.                         }
  1868.                     }
  1869.                 }
  1870.             } while(--h);
  1871.         }
  1872.         break;
  1873.  
  1874.     case FILTER_BILINEAR:
  1875. #ifdef USE_ASM
  1876. /*        asm_resize_interp_run(
  1877.                 dst,
  1878.                 src,
  1879.                 dstw,
  1880.                 dsth,
  1881.                 source->pitch,
  1882.                 dest->pitch,
  1883.                 accum_start(x_inc), //<0x8000 ? x_inc/2 : 0,
  1884.                 accum_start(y_inc), //<0x8000 ? y_inc/2 : 0,
  1885.                 x_inc,
  1886.                 y_inc);*/
  1887.  
  1888.         dest->StretchBltBilinearFast(
  1889.                 w_margin/2, h_margin/2,
  1890.                 dstw, dsth,
  1891.                 source,
  1892.                 0.0, 0.0,
  1893.                 source->w, source->h);
  1894.  
  1895. #else
  1896.         {
  1897.             y_accum = accum_start(y_inc);
  1898.  
  1899.             h = dsth;
  1900.             do {
  1901.                 unsigned long y_frac = (y_accum>>12)&15;
  1902.  
  1903.                 x_accum = accum_start(x_inc);
  1904.                 w = dstw;
  1905.                 do {
  1906.                     unsigned long *srct = src + (x_accum>>16);
  1907.                     unsigned long *srcb = (unsigned long *)((char *)srct + source->pitch);
  1908.                     unsigned long x_frac = (x_accum>>12)&15;
  1909.  
  1910.                     *dst++    =  (((((srct[0]&0xff00ff)*(16-x_frac) + (srct[1]&0xff00ff)*x_frac)*(16-y_frac)
  1911.                                 + ((srcb[0]&0xff00ff)*(16-x_frac) + (srcb[1]&0xff00ff)*x_frac)*y_frac) & 0xff00ff00)>>8)
  1912.                             |  (((((srct[0]&0x00ff00)*(16-x_frac) + (srct[1]&0x00ff00)*x_frac)*(16-y_frac)
  1913.                                 + ((srcb[0]&0x00ff00)*(16-x_frac) + (srcb[1]&0x00ff00)*x_frac)*y_frac) & 0x00ff0000)>>8);
  1914.  
  1915.                     x_accum += x_inc;
  1916.                 } while(--w);
  1917.  
  1918.                 dst = (unsigned long *)((char *)dst + dest->modulo);
  1919.  
  1920.                 y_accum += y_inc;
  1921.                 if (y_accum>>16) {
  1922.                     src = (unsigned long *)((char *)src + (y_accum>>16) * source->pitch);
  1923.                     y_accum &= 0xffff;
  1924.                 }
  1925.             } while(--h);
  1926.         }
  1927. #endif
  1928.         break;
  1929.  
  1930.     case FILTER_NONE:
  1931.         dest->StretchBltNearestFast(
  1932.                 w_margin/2, h_margin/2,
  1933.                 dstw, dsth,
  1934.                 source,
  1935.                 0.0, 0.0,
  1936.                 source->w, source->h);
  1937.         break;
  1938.  
  1939.     default:
  1940.         resize_table(mfd, source, dest, dst);
  1941.         break;
  1942.     }
  1943.  
  1944.     stats_print();
  1945.  
  1946.     return 0;
  1947. }
  1948.  
  1949. static long resize_param(FilterActivation *fa, const FilterFunctions *ff) {
  1950.     MyFilterData *mfd = (MyFilterData *)fa->filter_data;
  1951.  
  1952.     if (!mfd) return 0;
  1953.  
  1954.     if (mfd->fLetterbox) {
  1955.         fa->dst.w        = max(mfd->new_x, mfd->new_xf);
  1956.         fa->dst.h        = max(mfd->new_y, mfd->new_yf);
  1957.     } else {
  1958.         fa->dst.w        = mfd->new_x;
  1959.         fa->dst.h        = mfd->new_y;
  1960.     }
  1961.     fa->dst.AlignTo8();
  1962.  
  1963.     return FILTERPARAM_SWAP_BUFFERS;
  1964. }
  1965.  
  1966.  
  1967. static int resize_config(FilterActivation *fa, const FilterFunctions *ff, HWND hWnd) {
  1968.     MyFilterData *mfd = (MyFilterData *)fa->filter_data;
  1969.     MyFilterData mfd2 = *mfd;
  1970.     int ret;
  1971.  
  1972.     mfd->hbrColor = NULL;
  1973.     mfd->ifp = fa->ifp;
  1974.  
  1975.     if (mfd->new_x < 16)
  1976.         mfd->new_x = 320;
  1977.     if (mfd->new_y < 16)
  1978.         mfd->new_y = 240;
  1979.  
  1980. //    ret = DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_FILTER_RESIZE), hWnd, resizeDlgProc, (LONG)mfd);
  1981.  
  1982.     if (mfd->hbrColor) {
  1983.         DeleteObject(mfd->hbrColor);
  1984.         mfd->hbrColor = NULL;
  1985.     }
  1986.  
  1987.     if (ret)
  1988.         *mfd = mfd2;
  1989.  
  1990.     return ret;
  1991. }
  1992.  
  1993. static void resize_string(const FilterActivation *fa, const FilterFunctions *ff, char *buf) {
  1994.     MyFilterData *mfd = (MyFilterData *)fa->filter_data;
  1995.  
  1996.     if (mfd->fLetterbox)
  1997.         wsprintf(buf, " (%s, lbox %dx%d #%06x)", filter_names[mfd->filter_mode],
  1998.                 mfd->new_xf, mfd->new_yf, revcolor(mfd->rgbColor));
  1999.     else
  2000.         wsprintf(buf, " (%s)", filter_names[mfd->filter_mode]);
  2001. }
  2002.  
  2003. // this is really stupid...
  2004.  
  2005. static int permute_index(int a, int b) {
  2006.     return (b-(a>>8)-1) + (a&255)*b;
  2007. }
  2008.  
  2009. static void normalize_table(int *table, int filtwidth) {
  2010.     int i, j, v;
  2011.  
  2012.     for(i=0; i<256*filtwidth; i+=filtwidth) {
  2013.         v=0;
  2014.         for(j=0; j<filtwidth; j++)
  2015.             v += table[i+j];
  2016.  
  2017.         v = (0x4000 - v)/filtwidth;
  2018.         for(j=0; j<filtwidth; j++)
  2019.             table[i+j] += v;
  2020.  
  2021.         if (MMX_enabled) {
  2022.             for(j=0; j<filtwidth; j+=2) {
  2023.                 int a = table[i+j];
  2024.                 int b = table[i+j+1];
  2025.  
  2026.                 a = (a & 0xffff) | (b<<16);
  2027.  
  2028.                 table[i+j+0] = a;
  2029.                 table[i+j+1] = a;
  2030.             }
  2031.         }
  2032.  
  2033.         _RPT2(0,"table_error[%02x] = %04x\n", i, v);
  2034.     }
  2035. }
  2036.  
  2037. static bool generate_cubic_table(MyFilterData *mfd) {
  2038.     if (!(mfd->cubic4_tbl = new int[256*4*2]))
  2039.         return false;
  2040.  
  2041.     MakeCubic4Table(mfd->cubic4_tbl, -0.75, false);
  2042.     MakeCubic4Table(mfd->cubic4_tbl + 1024, -0.75, true);
  2043.  
  2044.     return true;
  2045. }
  2046.  
  2047. int resize_start(MyFilterData *mfd, VBitmap *src) {
  2048.     //MyFilterData *mfd = (MyFilterData *)fa->filter_data;
  2049.     long dstw = mfd->new_x;
  2050.     long dsth = mfd->new_y;
  2051.  
  2052.     if (dstw<16 || dsth<16)
  2053.         return 1;
  2054.  
  2055.     switch(mfd->filter_mode) {
  2056.  
  2057.     case FILTER_BICUBIC:
  2058.  
  2059.         if (!(mfd->cubic_rows = new Pixel[dstw * 4]))
  2060.             return 1;
  2061.  
  2062.         if (!generate_cubic_table(mfd))
  2063.             return 1;
  2064.  
  2065.         break;
  2066.  
  2067.     case FILTER_TABLEBILINEAR:
  2068.         {
  2069.             int i;
  2070.             long filtwidth_frac;
  2071.             double filtwidth_fracd;
  2072.             double filt_max;
  2073.  
  2074.             // 1:1 -> 2 input samples, max 16384
  2075.             // 2:1 -> 4 input samples, max 8192
  2076.             // 3:1 -> 6 input samples, max 5461
  2077.  
  2078.             if (src->w > dstw) {
  2079.  
  2080.                 filtwidth_fracd = src->w*256.0/dstw;
  2081.  
  2082.                 filtwidth_frac = ceil(filtwidth_fracd);
  2083.                 mfd->x_filtwidth = ((filtwidth_frac + 255) >> 8)<<1;
  2084.  
  2085.                 _RPT1(0,"x_filtwidth: %d\n", mfd->x_filtwidth);
  2086.  
  2087.                 if (!(mfd->x_table = new int[256 * mfd->x_filtwidth]))
  2088.                     return 1;
  2089.  
  2090.                 mfd->x_table[mfd->x_filtwidth-1] = 0;
  2091.  
  2092.                 filt_max = (dstw*16384.0)/src->w;
  2093.  
  2094.                 for(i=0; i<128*mfd->x_filtwidth; i++) {
  2095.                     int y = 0;
  2096.                     double d = i / filtwidth_fracd;
  2097.  
  2098.                     if (d<1.0)
  2099.                         y = (int)(0.5 + filt_max*(1.0 - d));
  2100.  
  2101.                     mfd->x_table[permute_index(128*mfd->x_filtwidth + i, mfd->x_filtwidth)]
  2102.                         = mfd->x_table[permute_index(128*mfd->x_filtwidth - i, mfd->x_filtwidth)]
  2103.                         = y;
  2104.                 }
  2105.             } else
  2106.                 mfd->x_filtwidth = 2;
  2107.  
  2108.  
  2109.  
  2110.             if (src->h > dsth) {
  2111.                 filtwidth_fracd = src->h*256.0/dsth;
  2112.                 filtwidth_frac = ceil(filtwidth_fracd);
  2113. //                filtwidth_frac = (src->h*256 + (dsth-1))/dsth;
  2114.                 mfd->y_filtwidth = ((filtwidth_frac + 255) >> 8)<<1;
  2115.  
  2116.                 if (!(mfd->y_table = new int[256 * mfd->y_filtwidth]))
  2117.                     return 1;
  2118.  
  2119.                 mfd->y_table[mfd->y_filtwidth-1] = 0;
  2120.  
  2121.                 filt_max = (dsth*16384.0)/src->h;
  2122.  
  2123.                 for(i=0; i<128*mfd->y_filtwidth; i++) {
  2124.                     int y = 0;
  2125.                     double d = i / filtwidth_fracd;
  2126.  
  2127.                     if (d<1.0)
  2128.                         y = (int)(0.5 + filt_max*(1.0 - d));
  2129.  
  2130. //                    if (i < filtwidth_frac)
  2131. //                        y = (int)(0.5 + (filt_max*(filtwidth_frac - i))/filtwidth_frac);
  2132.  
  2133.                     mfd->y_table[permute_index(128*mfd->y_filtwidth + i, mfd->y_filtwidth)]
  2134.                         = mfd->y_table[permute_index(128*mfd->y_filtwidth - i, mfd->y_filtwidth)]
  2135.                         = y;
  2136.                 }
  2137.  
  2138.             } else
  2139.                 mfd->y_filtwidth = 2;
  2140.  
  2141.             if (!(mfd->cubic_rows = new Pixel[((dstw+1)&~1) * mfd->y_filtwidth]))
  2142.                 return 1;
  2143.             if (!(mfd->row_table = new Pixel *[2*mfd->y_filtwidth-1]))
  2144.                 return 1;
  2145.  
  2146.             for(i=0; i<mfd->y_filtwidth; i++) {
  2147.                 mfd->row_table[i] = mfd->cubic_rows + ((dstw+1)&~1) * i;
  2148.                 if (i<mfd->y_filtwidth-1)
  2149.                     mfd->row_table[i+mfd->y_filtwidth] = mfd->cubic_rows + ((dstw+1)&~1) * i;
  2150.             }
  2151.         }
  2152.         break;
  2153.  
  2154.     case FILTER_TABLEBICUBIC:
  2155.         {
  2156.             int i;
  2157.             long filtwidth_frac;
  2158.             double filt_max;
  2159.  
  2160.             // 1:1 -> 2 input samples, max 16384
  2161.             // 2:1 -> 4 input samples, max 8192
  2162.             // 3:1 -> 6 input samples, max 5461
  2163.  
  2164.             if (src->w > dstw) {
  2165.                 filtwidth_frac = (src->w*256 + (dstw-1))/dstw;
  2166.                 mfd->x_filtwidth = ((filtwidth_frac + 255) >> 8)<<2;
  2167.  
  2168.                 _RPT1(0,"x_filtwidth: %d\n", mfd->x_filtwidth);
  2169.  
  2170.                 if (!(mfd->x_table = new int[256 * mfd->x_filtwidth]))
  2171.                     return 1;
  2172.  
  2173.                 mfd->x_table[mfd->x_filtwidth-1] = 0;
  2174.  
  2175.                 filt_max = (dstw*16384.0)/src->w;
  2176.  
  2177.                 for(i=0; i<128*mfd->x_filtwidth; i++) {
  2178.                     int y = 0;
  2179.                     double d = (double)i / (src->w*256.0/dstw);
  2180.  
  2181.                     if (d < 1.0)
  2182.                         y = (int)floor(0.5 + (1.0 - 2.0*d*d + d*d*d) * filt_max);
  2183.                     else if (d < 2.0)
  2184.                         y = (int)floor(0.5 + (4.0 - 8.0*d + 5.0*d*d - d*d*d) * filt_max);
  2185.  
  2186.                     mfd->x_table[permute_index(128*mfd->x_filtwidth + i, mfd->x_filtwidth)]
  2187.                         = mfd->x_table[permute_index(128*mfd->x_filtwidth - i, mfd->x_filtwidth)]
  2188.                         = y;
  2189.                 }
  2190.             } else
  2191.                 mfd->x_filtwidth = 4;
  2192.  
  2193.  
  2194.             if (src->h > dsth) {
  2195.  
  2196.                 filtwidth_frac = (src->h*256 + (dsth-1))/dsth;
  2197.                 mfd->y_filtwidth = ((filtwidth_frac + 255) >> 8)<<2;
  2198.  
  2199.                 if (!(mfd->y_table = new int[256 * mfd->y_filtwidth]))
  2200.                     return 1;
  2201.  
  2202.                 mfd->y_table[mfd->y_filtwidth-1] = 0;
  2203.  
  2204.                 filt_max = (dsth*16384.0)/src->h;
  2205.  
  2206.                 for(i=0; i<128*mfd->y_filtwidth; i++) {
  2207.                     int y = 0;
  2208.                     double d = (double)i / (src->h*256.0/dsth);
  2209.  
  2210. #if 0
  2211.                     if (d < 1.0)
  2212.                         y = (int)floor(0.5 + (1.0 - 2.0*d*d + d*d*d) * filt_max);
  2213.                     else if (d < 2.0)
  2214.                         y = (int)floor(0.5 + (4.0 - 8.0*d + 5.0*d*d - d*d*d) * filt_max);
  2215. #else
  2216. #define A (-0.75)
  2217.                     if (d < 1.0)
  2218.                         y = (int)floor(0.5 + (1.0 - (A+3.0)*d*d + (A+2.0)*d*d*d) * filt_max);
  2219.                     else if (d < 2.0)
  2220.                         y = (int)floor(0.5 + (-4.0*A + 8.0*A*d - 5.0*A*d*d + A*d*d*d) * filt_max);
  2221. #undef A
  2222.                     
  2223. #endif
  2224.  
  2225.                     mfd->y_table[permute_index(128*mfd->y_filtwidth + i, mfd->y_filtwidth)]
  2226.                         = mfd->y_table[permute_index(128*mfd->y_filtwidth - i, mfd->y_filtwidth)]
  2227.                         = y;
  2228.                 }
  2229.             } else
  2230.                 mfd->y_filtwidth = 4;
  2231.  
  2232.             if (!(mfd->cubic_rows = new Pixel[((dstw+1)&~1) * mfd->y_filtwidth]))
  2233.                 return 1;
  2234.             if (!(mfd->row_table = new Pixel *[2*mfd->y_filtwidth-1]))
  2235.                 return 1;
  2236.  
  2237.             if (src->h <= dsth || src->w <= dstw)
  2238.                 if (!generate_cubic_table(mfd))
  2239.                     return 1;
  2240.  
  2241.             for(i=0; i<mfd->y_filtwidth; i++) {
  2242.                 mfd->row_table[i] = mfd->cubic_rows + ((dstw+1)&~1) * i;
  2243.                 if (i<mfd->y_filtwidth-1)
  2244.                     mfd->row_table[i+mfd->y_filtwidth] = mfd->cubic_rows + ((dstw+1)&~1) * i;
  2245.             }
  2246.  
  2247.         }
  2248.         break;
  2249.     }
  2250.  
  2251.     if (mfd->x_table)
  2252.         normalize_table(mfd->x_table, mfd->x_filtwidth);
  2253.  
  2254.     if (mfd->y_table)
  2255.         normalize_table(mfd->y_table, mfd->y_filtwidth);
  2256.  
  2257.     return 0;
  2258. }
  2259.  
  2260. int resize_stop(MyFilterData *mfd) {
  2261.  
  2262.  
  2263.     delete[] mfd->cubic_rows;    mfd->cubic_rows = NULL;
  2264.     delete[] mfd->x_table;        mfd->x_table = NULL;
  2265.     delete[] mfd->y_table;        mfd->y_table = NULL;
  2266.     delete[] mfd->row_table;    mfd->row_table = NULL;
  2267.     delete[] mfd->cubic4_tbl;    mfd->cubic4_tbl = NULL;
  2268.  
  2269.     return 0;
  2270. }
  2271. // Resizer
  2272.  
  2273.  
  2274. #define SAR(DAR,hor,vert) (DAR*((double)hor/(double)vert))
  2275. PrepareResizer(int oxsize, int oysize, bool doAR ,double iDAR, int filterMode, VBitmap *source){
  2276.      double destSAR;
  2277.     int     rImageX, rImageY,yDestFirst;
  2278.  
  2279.     if(doAR){
  2280.     //Check input DAR (display aspect ratio)
  2281.         if(iDAR<=0) iDAR=1;
  2282.         if(iDAR>1) iDAR=1;
  2283.         //Working out desting Sample Aspect Ratio. Suppose ouput DAR as 3/4
  2284.         destSAR=SAR( ((double)3/(double)4), oxsize, oysize);
  2285.         //image dimentions
  2286.         rImageX=oxsize;
  2287.         rImageY= (rImageX*iDAR)/destSAR;
  2288.         yDestFirst=((oysize-rImageY)/2);
  2289.         if(yDestFirst<0){
  2290.             yDestFirst=0;
  2291.             rImageY=oysize;
  2292.         }
  2293.         
  2294.         mfd.fLetterbox=true;        
  2295.         mfd.filter_mode=filterMode;
  2296.         mfd.new_x=rImageX;
  2297.         mfd.new_y=rImageY;
  2298.         mfd.new_xf=oxsize;
  2299.         mfd.new_yf=oysize;
  2300.     }
  2301.     else{
  2302.         mfd.fLetterbox=false;        
  2303.         mfd.filter_mode=filterMode;
  2304.         mfd.new_x=oxsize;
  2305.         mfd.new_y=oysize;
  2306.     }
  2307.         resize_start(&mfd, source);
  2308. }
  2309.  
  2310. UnPrepareResizer(){
  2311.         resize_stop(&mfd);
  2312. }
  2313.  
  2314. ResizerRun(VBitmap *source, VBitmap *dest){
  2315.     resize_run(&mfd, source, dest);
  2316. }